﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Gueei.Gallery.Core.Entities;
using Gueei.Gallery.Core.Repositories;
using Newtonsoft.Json;

namespace Gueei.Gallery.JsonRepositories
{
	public class JsonTagRepository : ITagRepository
	{
		private List<Tag> _tags;
		private static Object _lock = new Object();

		public JsonTagRepository(string jsonDir)
		{
			Directory.CreateDirectory(jsonDir);
			JsonFilePath = Path.Combine(jsonDir, "tags.js");
			if (File.Exists(JsonFilePath))
			{
				try
				{
					string json = "";
					using (var fs = new StreamReader(JsonFilePath))
					{
						json = fs.ReadToEnd();
					}
					_tags = JsonConvert.DeserializeObject<List<Tag>>(json);
				}
				catch
				{
					_tags = new List<Tag>();
				}
			}
			else
			{
				_tags = new List<Tag>();
			}
		}

		protected string JsonFilePath
		{
			get;
			set;
		}

		public IQueryable<Tag> GetTags()
		{
			return _tags.AsQueryable();
		}

		public Tag GetTag(Guid id)
		{
			return GetTags().FirstOrDefault(t => t.Id.Equals(id));
		}

		public Tag GetTag(string name)
		{
			return GetTag(name, false);
		}

		public Tag GetTag(string name, bool create)
		{
			var temp = GetTags().FirstOrDefault(t => t.Name.Equals(name.ToLower()));
			if (temp != null) return temp;
			if (!create) return null;

			return CreateTag(name);
		}

		public bool SaveTag(Tag original)
		{
			SaveToJson();
			return true;
		}

		public Tag CreateTag(string name)
		{
			lock(_lock)
			{
				var trimmedName = name.Trim().ToLower();
				if (trimmedName.Equals(String.Empty))
					throw new ArgumentNullException("Name cannot be empty");
				var temp = GetTags().FirstOrDefault(t => t.Name.Equals(trimmedName));
				if (temp!=null) return temp;
				temp = new Tag()
				       	{
				       		Id = Guid.NewGuid(),
				       		Name = trimmedName
				       	};
				_tags.Add(temp);
				SaveToJson();
				return temp;
			}
		}

		private void SaveToJson()
		{
			var json = JsonConvert.SerializeObject(_tags);
			using (var fs = new StreamWriter(JsonFilePath))
			{
				fs.WriteLine(json);
			}
		}

		public IList<Tag> CreateOrReturnTags(string[] names)
		{
			ISet<Tag> tagSet = new SortedSet<Tag>();
			foreach(var tag in names.Select(n=>n.Trim()).Where(n=>n.Length>0).Select(n=> GetTag(n, true)))
			{
				tagSet.Add(tag);
			}
			return tagSet.ToList();
		}

		public bool TagExists(string name)
		{
			return _tags.FirstOrDefault(t => t.Name.Equals(name.ToLower())) != null;
		}
	}
}